package com.raorao.rpc.server;

import com.raorao.rpc.annotation.RaoRaoConfig;
import com.raorao.rpc.common.constants.ConfigConstant;
import com.raorao.rpc.common.utils.BeanPropertyUtils;
import com.raorao.rpc.server.model.ConfigModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.*;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * config处理者，自动下载配置信息、监听配置信息
 *
 * @author raorao
 * @since 1.0.0
 */
@Component
public class DefaultConfigProcessor implements ApplicationContextInitializer, ApplicationListener<ApplicationEvent>{

    private static Logger logger = LoggerFactory.getLogger(DefaultConfigProcessor.class);

    @Autowired
    private ConfigFileService configFileService;

    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        logger.debug("initialize");
    }

    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        if (applicationEvent instanceof ContextRefreshedEvent) {
            logger.debug("初始化配置中心客户端监听器...ContextRefreshedEvent");
            downLoadConfig(((ContextRefreshedEvent) applicationEvent).getApplicationContext());
        }else if (applicationEvent instanceof ContextClosedEvent) {
            logger.debug("ContextClosedEvent");
        }
    }

    /**
     * @description: 下载配置文件
     * @param: context
     * @return: void
     * @author raorao
     * @date: 2021/12/2 10:24
     */
    private void downLoadConfig(ApplicationContext context) {
        Map<String, Object> beans = context.getBeansWithAnnotation(RaoRaoConfig.class);
        List<String> filenames=new ArrayList<>();
        if (beans.size() != 0) {
            for (Object obj : beans.values()) {
                try {
                    Class<?> clazz = obj.getClass();
                    Class<?>[] interfaces = clazz.getInterfaces();
                    if (interfaces.length != 1) {
                        RaoRaoConfig service = clazz.getAnnotation(RaoRaoConfig.class);
                        String fileName = service.fileName();
                        if (fileName.equals("")|| StringUtils.isEmpty(fileName)) {
                            fileName= ConfigConstant.DEFAULT_FILE;
                            logger.debug("【raorao-config】The RaoRaoConfig filename use DEFAULT_FILE '" + obj.getClass().getName() + "'");
                        }
                        filenames.add(fileName);
                        bingBeanConfig(fileName,obj);
                        //监听节点
                        configFileService.watchConfig(fileName,obj);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * @description: 下载配置信息，并绑定数据
     * @param: value
     * @param: obj
     * @return: void
     * @author raorao
     * @date: 2021/12/9 14:09
     */
    private void bingBeanConfig(String fileName, Object obj) throws Exception{
        //1、获取配置信息，并插入到环境变量中
        StringBuilder configStr=new StringBuilder();
        configStr.append("# 【raorao-config】配置中心配置文件  ").append(fileName).append("\r\n");
        Map<String, ConfigModel> configModelMap = configFileService.getConfigFile(fileName);
        for (String key:configModelMap.keySet()){
            ConfigModel configModel = configModelMap.get(key);
            logger.debug("【raorao-config】设置变量{}：{}",configModel.getName(),configModel.getVal());
            System.setProperty(configModel.getName(),configModel.getVal());
            configStr.append(configModel.getName()).append("=").append(configModel.getVal()).append("\r\n");
        }
        //2、设置bean对象属性
        BeanPropertyUtils.changeBeanProperty(configModelMap,obj);
        //3、保存配置信息到文件
        configFileService.saveConfigFile(fileName,configStr.toString());
    }
}
